package cn.itsource.wechart.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpUtil;
import cn.itsource.basic.util.AjaxResult;
import cn.itsource.basic.util.RedisService;
import cn.itsource.org.domain.User;
import cn.itsource.org.domain.UserInfo;
import cn.itsource.org.mapper.UserMapper;
import cn.itsource.wechart.domain.*;
import cn.itsource.wechart.mapper.WxUserMapper;
import cn.itsource.wechart.service.IWeChartService;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;

@Service
@Slf4j //支持日志 提供log对象
public class WeCharServiceImpl implements IWeChartService {

    /**
     * 注册微信参数对象,为了拿到yml的参数值
     */
    @Autowired
    private WechartProperties wechartProperties;

    @Autowired
    private WxUserMapper wxUserMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisService redisService;

    @Override
    public String toLogin() {
        /**
         * 第一大步:重定向到扫描页面
         *      跳转扫描页码url完整整出来,重定向回去
         */
        //1.拿到重定的url
        //https://open.weixin.qq.com/connect/qrconnect?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_login&state=%s#wechat_redirect
        String url = wechartProperties.getAuthorizationCodeUrl();

        //2.替换这个url里面的%s
        String appId = wechartProperties.getAppId();
        String redirectUri = wechartProperties.getRedirectUri();
        String state = IdUtil.fastSimpleUUID();
        String formatUrl = String.format(url, appId, redirectUri, state);

        //https://open.weixin.qq.com/connect/qrconnect?appid=wxd853562a0548a7d0&redirect_uri=http://bugtracker.itsource.cn/wechart/callback&response_type=code&scope=snsapi_login&state=747a4af0f3b447eb800bc8d9f8252373#wechat_redirect
        log.info("重定向的url,{}", formatUrl);

        return "redirect:" + formatUrl;
    }

    @Override
    public String callback(String code) {

        /**
         * 第二大步,通过code 和appid 和appscret 拿到access_token
         */
        //1.获取yml的获取token的地址值
        //https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code
        String tokenUrl = wechartProperties.getTokenUrl();

        //2.拿到appid ,appsecret,code,拼接url
        String appId = wechartProperties.getAppId();
        String appSecrect = wechartProperties.getAppSecrect();
        //3.拼接url,替换%s
        tokenUrl = String.format(tokenUrl, appId, appSecrect, code);

        //4.发送http请求获取返回的数据
        String tokenResult = HttpUtil.get(tokenUrl);
        log.info("获取token的url访问之后返回的结果,{}", tokenResult);

        //{"access_token":"65_VPP7ntbq9p_etKMVRgQtJiL61Gv-JiCzjuR7qumIi58C-zOREmCXPb7cd6m_DjWVDbksI7YySWPpF7JBJlM9blonqGQ3_tIJ407LwP6kOAY","expires_in":7200,"refresh_token":"65_9ZxOcITFqtVnD0rvnFjbkRFzHEy1v5uxGIb8DuOxVucmSG7tmv-sanZ6qrW9iIsjags3oaFktEqMp2WPbgEeYlFIBTjEpTIIpPd9Zu0IgqU","openid":"oa9wA00V9M6vqF8KP7hUJ5jomSE8","scope":"snsapi_login","unionid":"ovnCWw4QbFhFeH-I3xr05lCtj1CM"}

        /**
         * 第三大步:通过token获取用户的资源信息
         */
        //1.获取用户资源的url https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s
        String userinfoUrl = wechartProperties.getUserinfoUrl();
        //2.fastJson包 ,通过它把json字符串的值,赋值到对象中
        WechartTokenDto wechartTokenDto = JSONObject.parseObject(tokenResult, WechartTokenDto.class);

        log.info("token的dto对象,{}", wechartTokenDto);
        //3.拼接url
        userinfoUrl = String.format(userinfoUrl, wechartTokenDto.getAccess_token(), wechartTokenDto.getOpenid());

        //4.调用这个url http请求
        String userInfoResult = HttpUtil.get(userinfoUrl);
        log.info("返回的用户资源,{}", userInfoResult);

        WechartUserInfoDto wechartUserInfoDto = JSONObject.parseObject(userInfoResult, WechartUserInfoDto.class);
        log.info("用户对象,{}", wechartUserInfoDto);

        /**
         * 情况一:第一次扫码这个系统
         */
        String bindUrl = "redirect:http://bugtracker.itsource.cn:8081/binder.html";

        //1.通过openid查询t_wxuser表,
        String openid = wechartUserInfoDto.getOpenid();
        WxUser dbWxUser = wxUserMapper.findbyOpenid(openid);
        //2.如果没有查到,新增一条t_wxuser的数据
        if (dbWxUser == null) {
            WxUser wxUser = BeanUtil.copyProperties(wechartUserInfoDto, WxUser.class);
            wxUserMapper.insertSelective(wxUser);
            //3.重定向到绑定页面
            return bindUrl + "?openid=" + openid;
        }

        /**
         * 情况二:数据特别完整
         * 1.通过openid可以拿到t_wxuser的对象
         * 2.t_wxuser对象有user_id
         * 3.user_id可以查到user对象
         * 4.user有绑定好的手机号
         * 5.存redis token UserInfo
         * 6.跳转到首页
         */
        // 1.t_wxuser对象有user_id
        Long userId = dbWxUser.getUserId();
        if (userId != null){
            // 2.user_id可以查到user对象
            User user = userMapper.selectByPrimaryKey(userId);
            // 3.user有绑定好的手机号
            if (user != null && StringUtils.isNotBlank(user.getPhone())){

                // 4.存redis token UserInfo
                //5.redis存key :token  值 ,UserInfo对象
                String token = IdUtil.fastSimpleUUID();
                UserInfo userInfo = BeanUtil.copyProperties(user, UserInfo.class);
                userInfo.setToken(token);
                //设置用户id
                userInfo.setUserId(user.getId());

                redisService.setStringKeyAndValue(token, userInfo, 30);
                // 5.跳转到首页没有走绑定流程 token要回去 ,phone给前端
                return "redirect:http://bugtracker.itsource.cn:8081/index.html?token=" + token + "&phone=" + user.getPhone();
            }

        }

        //3.第三种情况处理完成
        return bindUrl + "?openid=" + openid;
    }

    /**
     * 绑定流程
     *
     * @param binderDto
     * @return
     */
    @Override
    public AjaxResult binder(BinderDto binderDto) {

        //1.判断验证码
        String redisCode = redisService.getKeyObjectValue(binderDto.getPhone());
        if (!StringUtils.equals(redisCode, binderDto.getCode())) {
            throw new RuntimeException("验证码错误");
        }

        /**
         * 分情况
         * 一:输的手机号,能够拿到对象
         *
         * 二:手机号拿不到对象
         */
        //1.根据手机号获取用户表t_user的数据
        String phone = binderDto.getPhone();
        User phoneUser = userMapper.findByPhone(phone);

        //2.如果能获取到,绑定获取到的账号
        Long userId = null;
        User newUser = null;
        if (phoneUser != null) {
            userId = phoneUser.getId();
            newUser = phoneUser;
        } else {
            //3.如果不能获取到,注册一个账号,再来绑定
            User user = new User();
            user.setPassword("123");//默认密码
            user.setPhone(phone);
            user.setCreatetime(new Date());
            user.initPwd();

            newUser = user;
            //3.1入库
            userMapper.insertSelective(user);
            userId = user.getId();
        }

        //4.t_wxuser来绑定外键user_id
        //4.1通过openid查询到t_wxuser的对象
        String openid = binderDto.getOpenid();
        WxUser wxUser = wxUserMapper.findbyOpenid(openid);

        wxUser.setUserId(userId);

        //4.2修改wxuser对象
        wxUserMapper.updateByPrimaryKeySelective(wxUser);

        //5.redis存key :token  值 ,UserInfo对象
        String token = IdUtil.fastSimpleUUID();
        UserInfo userInfo = BeanUtil.copyProperties(newUser, UserInfo.class);
        userInfo.setToken(token);
        //设置用户id
        userInfo.setUserId(newUser.getId());

        redisService.setStringKeyAndValue(token, userInfo, 30);

        //跳转到页面,登录成功  ,seesionstoage必须要有token  ,redis也要有数据
        return AjaxResult.createSuccess(userInfo);
    }


}
